#!/usr/bin/env python
# -*- coding: utf-8 -*-
# datetime: 11/12/2023 下午10:57
# Author: name
# File: api_test.py
# ide: PyCharm
# description:

import json
import re

import jmespath
import requests
from pywebio.output import *
from pywebio.pin import *
from frontend.menus import show_menus

error_msg = {}


def handle_params(params):
    if params:
        if "{" in params and "}" in params:
            params = json.loads(params)
        else:
            params_list = params.split("\n")
            params = {}
            # print(params)
            for p in params_list:
                if ":" in p:
                    key = p.split(":")[0]
                    if p.split(":")[1][0] == " ":
                        value = p.split(":")[1][1:]
                    else:
                        value = p.split(":")[1]
                    params[key] = value
        return params
    else:
        return None


file = None


def upload_file():
    global file
    print(file)
    up_file = pin.file_content
    print(up_file)


def remove_file_data():
    pin_update("file_content", value="")
    pin_update("file_key", value="")


def assert_result(actual_result, expect_result):
    # print(actual_result)
    # print(expect_result)
    success_result = {}
    fail_result = {}
    if str(actual_result)[0] == "{" or str(actual_result)[0] == "[":
        for assert_line in expect_result.split("\n"):
            if "==" in assert_line:
                jms_expression = assert_line.split("==")[0]
                jms_result = jmespath.search(jms_expression, actual_result)
                result = assert_line.split("==")[1]
                result = result.replace("'", "").replace('"', '').replace(" ", "")
                if jms_result:
                    if str(jms_result) == result:
                        success_result[assert_line] = f"{jms_result}=={result}"
                    else:
                        fail_result[assert_line] = f"{jms_result}=={result}"

    return len(success_result.keys()), success_result, len(fail_result), fail_result


def send_request():
    headers = handle_params(pin.request_header)
    params = handle_params(pin.request_params)
    data = handle_params(pin.request_data)
    method = pin.method
    url = pin.url
    files = {}
    pin_update("method", value=method)
    pin_update("url", value=url)

    if file:
        key = pin.file_key
        if key:
            files[key] = (file["filename"], file["content"], file["mime_type"])
    if url:
        pin_update("result_body", value="请求发送中")
        response = requests.request(method=method, url=url, headers=headers, params=params, json=data, files=files,
                                    verify=False)
        response_header = dict(response.headers)
        # 处理断言
        request_assert = pin.request_assert
        assert_text = {
            "assert_total": 0,
            "assert_failure": {},
            "assert_success": {}
        }
        if request_assert:
            success_total, success, failure_total, failure = assert_result(response.json(), request_assert)
            assert_text["assert_total"] = success_total + failure_total
            assert_text["assert_failure"]["failure_total"] = failure_total
            assert_text["assert_failure"]["failure"] = failure
            assert_text["assert_success"]["success_total"] = success_total
            assert_text["assert_success"]["success"] = success
        # pin_update("result_body", value=FormatCode(response.text)[0])
        try:
            response_data = json.dumps(response.json(),ensure_ascii=False,indent=4)
        except:
            response_data = response.text
        pin_update("result_body", value=response_data)
        pin_update("result_code", value=response.status_code)
        pin_update("result_headers", value=json.dumps(response_header,ensure_ascii=False,indent=4))
        assert_text = json.dumps(assert_text,ensure_ascii=False,indent=4)
        space_re_expression = re.compile('(:\n\s\s\s*?)"', re.S)
        space_result_list = re.findall(space_re_expression, assert_text)
        for space in space_result_list:
            assert_text = assert_text.replace(space, ": ")
        pin_update("result_assert", value=assert_text)
        toast(content="请求发送成功", color="green", duration=1, position="center")
    else:
        toast(content="请输入接口地址", color="red", duration=1, position="center")


def html_show_api_test():
    """
    接口测试

    """
    show_menus()

    put_row([
        put_tabs(
            [
                {
                    "title": "接口测试工具",
                    "content":
                        [
                            put_row(
                                [
                                    put_select(name="method", options=["GET", "POST", "PUT", "PATCH", "DELETE"]),
                                    None,
                                    put_input(name="url", placeholder="请输入接口地址"),
                                    None,
                                    put_button("发送", onclick=send_request),
                                ], size="10% 2% 78% 2% 10%"
                            ),
                            put_text("Request"),
                            put_row(
                                [
                                    put_tabs(
                                        [
                                            {
                                                "title": "headers",
                                                "content": [
                                                    put_textarea(name="request_header", rows=10, value="",
                                                                 placeholder="键值对参数: key:value 多个键值之间需要换行")
                                                ]
                                            },
                                            {
                                                "title": "params",
                                                "content": [
                                                    put_textarea(name="request_params", rows=10, value="",
                                                                 placeholder="键值对参数: key:value 多个键值之间需要换行")
                                                ]
                                            },
                                            {
                                                "title": "data",
                                                "content": put_textarea(name="request_data", rows=10, value="",
                                                                        placeholder="键值对参数: key:value 多个键值之间需要换行")
                                            },
                                            {
                                                "title": "file",
                                                "content": [
                                                    put_row(
                                                        [
                                                            put_input("file_key", placeholder="file_key"),
                                                            None,
                                                            put_file_upload("file_content", multiple=True),
                                                            None,
                                                            put_button("上传", onclick=lambda: upload_file()),
                                                            put_button("清除", onclick=remove_file_data, color="danger")
                                                        ], size="15% 3% 55% 3% 8% 8%"
                                                    )

                                                ]
                                            },
                                            {
                                                "title": "assert",
                                                "content": put_textarea(name="request_assert", rows=10, value="",
                                                                        placeholder="请输入断言 a==b (a:实际返回数据节点名称,b:期望值)")
                                            }
                                        ]
                                    )
                                ]
                            ),
                            put_text("Response"),
                            put_row(
                                [
                                    put_tabs(
                                        [
                                            {
                                                "title": "response",
                                                "content": [
                                                    put_textarea(name="result_body", rows=10, value="")
                                                ]
                                            },
                                            {
                                                "title": "code",
                                                "content": put_textarea(name="result_code", rows=10, value="")

                                            },

                                            {
                                                "title": "cookies",
                                                "content": [
                                                    put_textarea(name="result_cookies", rows=10, value="")
                                                ]
                                            },
                                            {
                                                "title": "headers",
                                                "content": [
                                                    put_textarea(name="result_headers", rows=10, value="")
                                                ]
                                            },
                                            {
                                                "title": "test results",
                                                "content": [
                                                    put_textarea(name="result_assert", rows=10, value="")
                                                ]
                                            }
                                        ]
                                    )
                                ]
                            )
                        ]
                }

            ]
        )

    ], scope="data_list")
